package com.hoshino.momochi.service.Impl;

import com.hoshino.momochi.mapper.MessageListMapper;
import com.hoshino.momochi.mapper.MessageMapper;
import com.hoshino.momochi.mapper.UserMapper;
import com.hoshino.momochi.model.DTO.MessageDTO;
import com.hoshino.momochi.model.domain.Message;
import com.hoshino.momochi.model.domain.MessageList;
import com.hoshino.momochi.service.MessageService;
import com.hoshino.momochi.service.RedisService;
import com.hoshino.momochi.service.SseService;
import com.hoshino.momochi.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Service
public class SseServiceImpl implements SseService {

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MessageListMapper messageListMapper;

    private static Map<Long, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();

    /**
     * 连接 sse
     *
     * @param uid
     * @return SseEmitter
     */
    @Override
    public SseEmitter connect(Long uid) {
        if (sseEmitterMap.containsKey(uid)) {
            // 已经存在该连接 删除旧连接 创建新连接
//            sseEmitterMap.get(uid).complete();
            sseEmitterMap.remove(uid);
        }
        // 不设置超时时间
        SseEmitter sseEmitter = new SseEmitter(0L);
        // 连接成功需要返回数据，否则会出现待处理状态
        try {
            sseEmitter.send(SseEmitter.event().comment("welcome"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        sseEmitter.onCompletion(() -> {
            sseEmitterMap.remove(uid);
        });

        sseEmitter.onTimeout(() -> {
            sseEmitterMap.remove(uid);
        });

        // 连接报错
        sseEmitter.onError((throwable) -> {
            sseEmitterMap.remove(uid);
        });

        sseEmitterMap.put(uid, sseEmitter);
        log.info("SSE连接建立,{}", sseEmitterMap);

        return sseEmitter;
    }


    /**
     * 一对一发送消息
     *
     * @param uid     指定用户
     * @param message JSON 数据
     */
    @Override
    public boolean sendMessage(Long sendId, Long uid, String message) {
        try {
            SseEmitter sseEmitter = sseEmitterMap.get(uid);
            if (sseEmitter == null) {
                // 没有 这个 用户
                log.info("id:{},的用户不存在或不在线", uid);
                Long checkId = userMapper.getUserIdById(uid);
                if (checkId == null) {
                    log.info("id{}，用户不存在", uid);
                } else {
                    // 缓存消息
                    log.info("id{},用户离线", uid);
                    MessageDTO m = new MessageDTO(sendId, uid, message);
                    redisService.MessageCache(uid, m);
                }
                return false;
            } else {
                // 发送消息
                log.info("发送消息到 指定用户");
                sseEmitter.send(message, MediaType.APPLICATION_JSON);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 消息列表更新
            MessageList upItem = new MessageList();
            upItem.setUserId(sendId);
            upItem.setTargetId(uid);
            upItem.setCreateTime(new Date());
            messageListMapper.updateCreateTime(upItem);
            // 添加消息
            Message m = new Message(sendId, uid, message);
            m.setCreateTime(new Date());
            messageMapper.addMessage(m);
        }
        return true;
    }

    @Override
    public void closeConnect(Long uid) {
        sseEmitterMap.remove(uid);
    }
}
